{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 《.NET/C#面试手册》\n",
    "\n",
    ".NET/C#⾯试题汇总系列：基础语法 \n",
    "\n",
    ".NET/C#⾯试题汇总系列：⾯向对象 \n",
    "\n",
    ".NET/C#⾯试题汇总系列：集合、异常、泛型、LINQ、委托、EF！ \n",
    "\n",
    ".NET/C#⾯试题汇总系列：多线程 \n",
    "\n",
    ".NET/C#⾯试题汇总系列：ASP.NET MVC \n",
    "\n",
    ".NET/C# ⾯试题汇总系列：ASP.NET Core \n",
    "\n",
    ".NET/C#⾯试题汇总系列：ADO.NET、XML、HTTP、AJAX、WebService \n",
    "\n",
    ".NET/C#⾯试题汇总系列：常⻅的算法 \n",
    "\n",
    ".NET/C#⾯试题汇总系列：数据库概念知识 \n",
    "\n",
    ".NET/C#⾯试题汇总系列：数据库SQL查询（附建表语句）\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# .NET/C#⾯试题汇总系列：基础语法\n",
    "\n",
    "#### 1. 字符串string str = null 和 string str =\"\" 和string str = string.Empty的区别？\n",
    "\n",
    "string.Empty相当于“” ，Empty是一个静态只读的字段。string str = \"\",初始化对象，并分配一个空的内存空间 string  str = null ,初始化对象，不会分配内存空间\n",
    "\n",
    "\n",
    "\n",
    "#### 2. byte b='a' ;byte c = 1 ;byte d = 'ab' ; byte e = '啊'; byte g  = 256;这些变量有哪些错误是错在哪里？\n",
    "\n",
    "本题考查的是数据类型能承载的数据的大小。\n",
    "1byte = 8bit ,一个汉字=2byte,一个英文= 1byte = 8bit\n",
    "所以bc 是对的 ，edg是错的。'a' 是char类型，a错误\n",
    "java byte 取值范围是-128-127， 而C#一个byte是0-255\n",
    " \n",
    "\n",
    " #### 3.string和StringBuilder的区别,两者性能的⽐较\n",
    "\n",
    " 都是引用类型，分配再堆上\n",
    " - StringBuilder默认容量是16，可以允许扩充它所封装的字符串中字符的数量。每个StringBuffer对象都有一定的缓冲区容量，当字符串的大小没有超过容量时，不会分配新的容量，当字符串大小超过容量时，会自动增加容量。\n",
    "\n",
    " - 对于简单的字符串连接操作，在性能比较少的情况下，过度滥用stringBuilder会导致性能的浪费而非节约，只有大量无法预知次数的字符串才考虑使用stringbuilder的使用。从最后分析可以看出如果是相对较少的字符串拼接根本看不出太大区别。\n",
    "\n",
    "- Stringbuilder的使用，最好制定合适的容量值，否则优于默认值容量不足而频繁的进行内存分配操作。是不妥的实现方式。\n",
    "\n",
    " [参考链接](https://www.cnblogs.com/haofuqi/p/4826262.html \"String和StringBuilder的深入解析\")\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4.什么是扩展方法？\n",
    "\n",
    "一句话解释，扩展方法使你能够向现有类型“添加方法” ，无需修改类型\n",
    "条件：按扩展方法必须满足的条件 \n",
    "    1.必须要静态类中的静态方法 \n",
    "    2.第一个参数的类型是要拓展的类型并且需要添加this关键字以标识为拓展方法\n",
    "    \n",
    "建议：通常，只在不得已的情况下才实现扩展方法，并谨慎的实现\n",
    "\n",
    "使用:不能通过雷明调用，直接使用类型来调用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### 5.byte a =255;a+=5;a的值是多少？\n",
    "\n",
    "byte的取值范围是-2的8次⽅⾄2的8次⽅-1，-256⾄258，a+=1时，a的值时0，a+=5时，a的值是0，所 以a+=5时，值是4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a的值为4\n"
     ]
    }
   ],
   "source": [
    "byte a = 255;\n",
    "a+=5;\n",
    "Console.WriteLine(\"a的值为{0}\",a);      "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 6.什么是装箱和拆箱?\n",
    "\n",
    "装箱就是隐式地将⼀个值类型转换成引⽤类型，如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [],
   "source": [
    " int i=0;\n",
    " System.Object obj = i;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "拆箱就是将引用类型转成值类型，如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "int i=0;\n",
    "System.Object obj = i;\n",
    "int j = (int)obj; //将obj拆箱"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#####  经典面试题\n",
    "请问下面代码涉及到几次拆箱和装箱\n",
    "``` C# \n",
    "{\n",
    "    int m1 = 20;\n",
    "    object m2 = m1;\n",
    "    Console.WriteLine(m1+\",\"+(int)m2);\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "分析:\n",
    "\n",
    "1. 第一次装箱发生在 object m2 = m1;\n",
    "\n",
    "2. 第一次拆箱发生在 (int)m2 上;\n",
    "\n",
    "　所以很多人认为答案是：1次装箱和1次拆箱，显然是不对的。\n",
    "\n",
    "　　　我们继续分析，熟悉 Console.WriteLine原理的知道内部调用string.Concat()方法进行拼接，而Contact有很多重载，F12看源码可知，\n",
    "\n",
    "![截图](image/1_6.png)\n",
    "\n",
    "\n",
    "　　　该案例只能使用 public static String Concat(object arg0, object arg1); 这个重载，\n",
    "\n",
    "　　　所以第2次装箱和第3次装箱发生在 m1→object 和（int）m2→object上。\n",
    "\n",
    "　　所以最终答案是 1次拆箱和3次装箱"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 特别注意\n",
    "\n",
    "　　用什么类型进行装箱的，拆箱就拆成什么类型，否则会抛异常，无法进行类型转换。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 7.值类型和引用类型的区别\n",
    "\n",
    "值类型变量是直接包含值。将一个值类型赋给另一个值类型变量，是复制包含的值，默认是0。\n",
    "\n",
    "引用类型变量的赋值只复制对对象的引用，而不复制对象本身，默认值是null。\n",
    "\n",
    "值类型有整形、浮点型、bool、枚举\n",
    "\n",
    "应用类型有class、delegate、Object、string\n",
    "\n",
    "值类型储存在栈中，引用类型储存在堆中"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 8.new关键字的作用？\n",
    "\n",
    "运算符：创建对象实例\n",
    "\n",
    "修饰符：在派生类定义一个重名的方法，隐藏掉基类方法\n",
    "\n",
    "约束：泛型约束定义，约束可使用的泛型类型，如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "public class ItemFactory<T> where T : IComparable, new() \n",
    "{ \n",
    "\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 9.int?和int 有什么区别？\n",
    "\n",
    "int? 可为空类型，默认值可以是null\n",
    "\n",
    "int默认值是0\n",
    "\n",
    "int?是通过int装箱为引用类型实现"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 10.C#中委托是什么？\n",
    "\n",
    "一句话解释就是：将方法当作参数传入另一个方法的参数。\n",
    ".net中有很多常见的委托如：Func、Action\n",
    "\n",
    "作用：提高方法的拓展性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 11.最有效的方法算数2乘以8等于几？\n",
    "\n",
    "位运算是最快，使⽤的是位运算 逻辑左位移<<。 ⽅法是2<<3相当于0000 0000 0000 0010 （2的16位 int⼆进制）左移三位就是 0000 0000 0001 0000（16的⼆进制）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3*8=16\n"
     ]
    }
   ],
   "source": [
    "int num = 2<<3;\n",
    "Console.WriteLine(\"3*8={0}\",num); "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 12. const 和readonly 有什么区别？\n",
    "\n",
    "1. 初始化位置不同。const必须在声明的同时赋值；readonly即可以在声明处赋值，也可以在静态方法(必须是静态构造方法，普通构造方法不行)里赋值。\n",
    "\n",
    "2. 修饰对象不同。const即可以修饰类的字段，也可以修饰局部变量；readonly只能修饰类的字段。\n",
    "\n",
    "3. const是编译时常量，在编译是确定该值；readonly是运行时常量，在运行是确定该值。\n",
    "\n",
    "4. const 默认是静态的；而readonly如果设置成静态需要显示声明。\n",
    "\n",
    "5. 修饰引用类型时不同，const修饰string或值为null 的其他引用类型；readonly可以时任何类型。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 13.现有⼀个整数number，请写⼀个⽅法判断这个整数是否是2的N次⽅\n",
    "\n",
    "4（100）、5（101）、8（1000）、16（10000） \n",
    "\n",
    "取模运算： ⽤number%2==0可以判断，但是这个有点低级 \n",
    "\n",
    "位运算：（使⽤位运算逻辑并，两个位上的都为1才是1，其余都是0，判断是否等于0）\n",
    "\n",
    "4&3相当于100&011 ，结果是000等于0，所以4是2的n次⽅ \n",
    "\n",
    "5&4相当于101&100，结果是100不等于0，所以5不是2的n次⽅ \n",
    "\n",
    "如果要问如果是2的N次⽅，这个N是多少？这该怎么算？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1024是2的10次方\n"
     ]
    }
   ],
   "source": [
    "private static byte get (int n)\n",
    "{\n",
    "    byte number = 1;\n",
    "    while (n/2!=1)\n",
    "    {\n",
    "        n=n/2;\n",
    "        number +=1;\n",
    "    }\n",
    "    return number;\n",
    "}\n",
    "int num  = 1024;\n",
    "Console.WriteLine(\"{0}是2的{1}次方\",num,get(1024)); //计算1024是2的几次饭"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 14.CTS、CLS、CLR分别作何解释?\n",
    "\n",
    "CTS：通用语言系统。CLS：通用语言规范。CLR：公共语言运行库。\n",
    "\n",
    "CTS：Common type System 通用类型系统。Int32、 Int16 $\\rightarrow$ int、String $\\rightarrow$ string、 Boolean $\\rightarrow$ bool。每种语言都定义了自己的类型，.Net通过CTS提供了公共的类型，然后翻译生成对应的.Net类型。\n",
    "\n",
    "CLS: Common Language Specification 通⽤语⾔规范。不同语⾔语法的不同。每种语⾔都有⾃⼰的语 法，.Net通过CLS提供了公共的语法，然后不同语⾔翻译⽣成对应的.Net语法。\n",
    "\n",
    "CLR：Common Language Runtime 公共语⾔运⾏时，就是GC、JIT等这些。有不同的CLR，⽐如服务 器CLR、Linux CLR（Mono）、Silverlight CLR(CoreCLR)。相当于⼀个发动机，负责执⾏IL。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 15.在.net中，配件的意思是？\n",
    "\n",
    "晨旭集。（中间语言，源数据，资源，装配清单）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 16.分析下面代码，a、b 的值是多少"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a=11,b=5\n"
     ]
    }
   ],
   "source": [
    "string strTmp = \"a1某某某\"; \n",
    "int a = System.Text.Encoding.Default.GetBytes(strTmp).Length; \n",
    "int b = strTmp.Length;\n",
    "\n",
    "\n",
    "\n",
    "//在不同的编码下大小不同。utf-8中   一个字母、数字占一个byte、中文是3个byte\n",
    "Console.WriteLine(\"a={0},b={1}\",a,b);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[参考连接](https://blog.csdn.net/u010737354/article/details/52456570)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 17.Strings = new String(“xyz”);创建了⼏个String Object?\n",
    "\n",
    "两个对象，⼀个是“xyz”,⼀个是指向“xyz”的引⽤对象s。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 18.静态成员和⾮静态成员的区别\n",
    "\n",
    "1.静态成员statis修饰符声明，在类被实例化时被创建，通过类进行访问\n",
    "\n",
    "2.不带statis的变量时非静态变量，在对象被实例化时创建，通过对象进行访问。\n",
    "\n",
    "3.静态方法里不能使用非静态成员，非静态方法可以使用静态成员\n",
    "\n",
    "4.静态成员属于类，而不属于对象"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "####  19.c#可否对内存直接操作\n",
    "\n",
    "C#在unsafe 模式下可以使⽤指针对内存进⾏操作, 但在托管模式下不可以使⽤指针，C#NET默认不运⾏ 带指针的，需要设置下，选择项⽬右键->属性->选择⽣成->“允许不安全代码”打勾->保存"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 20.short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?\n",
    "\n",
    "s1+1不能显式转换成short类型，可以修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 21.什么是强类型，什么是弱类型？哪种更好些？为什么?\n",
    "\n",
    "强类型是在编译的时候就确定类型的数据，在执⾏时类型不能更改，⽽弱类型在执⾏的时候才会确定类 型。没有好不好，⼆者各有好处，强类型安全，因为它事先已经确定好了，⽽且效率⾼。 ⼀般⽤于编译型编程语⾔，如c++,java,c#,pascal等,弱类型相⽐⽽⾔不安全，在运⾏的时候容易出现错 误，但它灵活，多⽤于解释型编程语⾔，如javascript,vb,php等"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 22.using关键字的作⽤\n",
    "\n",
    "1.引⽤命名空间，也可using 别名 \n",
    "\n",
    "2.释放资源，实现了IDisposiable的类在using中创建，using结束后会⾃定调⽤该对象的Dispose⽅法， 释放资源。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 23.ref和out有什么区别\n",
    "\n",
    "1.都是按引用类型进行传递\n",
    "\n",
    "2.属于不是变量不能作为out、ref参数传递\n",
    "\n",
    "3.ref参数必须初始化。out不需要初始化\n",
    "\n",
    "4.作用，当方法有多个返回值时，out非常有用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 24.a.Equals(b)和a==b⼀样吗？\n",
    "\n",
    "不⼀样，a==b仅仅表示a和b值相等，a.Equals(b)表示a与b⼀致"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 25.下⾯这段代码求值\n",
    "\n",
    "``` C#\n",
    "class Class1  \n",
    "{ \n",
    "    internal static int count = 0; \n",
    "    static Class1() \n",
    "    { \n",
    "        count++; \n",
    "    } \n",
    "    public Class1() \n",
    "    { \n",
    "        count++; \n",
    "    } \n",
    "} \n",
    "Class1 o1 = new Class1(); \n",
    "Class1 o2 = new Class1();\n",
    "```\n",
    "\n",
    "o1.count的值是多少？ 答案：3，静态 构造⽅法计算⼀次，两个实例化对象计算两次。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "vscode": {
     "languageId": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count=3\n"
     ]
    }
   ],
   "source": [
    "public class Class1  \n",
    "{ \n",
    "    public static int count = 0; \n",
    "    static Class1() \n",
    "    { \n",
    "        count++; \n",
    "    } \n",
    "    public Class1() \n",
    "    { \n",
    "        count++; \n",
    "    }\n",
    "    public int Out(){\n",
    "        Console.WriteLine(\"count={0}\",count);\n",
    "        return 0;\n",
    "    }\n",
    "} \n",
    "Class1 o1 = new Class1(); \n",
    "Class1 o2 = new Class1();\n",
    "\n",
    "o1.Out();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 26.关于构造函数说法正确的是哪个？\n",
    "\n",
    "a)构造函数可以声明返回类型。 \n",
    "\n",
    "b)构造函数不可以⽤private修饰 \n",
    "\n",
    "c)构造函数必须与类名相同 \n",
    "\n",
    "d)构造函数不能带参数\n",
    "\n",
    "\n",
    "答案：c ，构造函数必须与类名相同，可以传递多个传递，作⽤就是便于初始化对象成员，不能有任何返 回类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 27.Math.Round(11.5)等於多少? Math.Round(-11.5)等於多少?\n",
    "\n",
    "Math.Round(11.5)=12\n",
    "\n",
    "Math.Round(-11.5)=-12"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 28.&和&&的区别\n",
    "\n",
    "相同点 \n",
    "\n",
    "&和&&都可作逻辑与的运算符，表示逻辑与（and），当运算符两边的表达式的结果都为true时，其结果 才为true，否则，只要有⼀⽅为false，则结果为false。（ps：当要⽤到逻辑与的时候&是毫⽆意义，&本 身就不是⼲这个的） \n",
    "\n",
    "不同点\n",
    "\n",
    " ``` if(loginUser!=null&&string.IsnullOrEmpty(loginUser.UserName)) ``` \n",
    " \n",
    " &&具有短路的功能，即如果第⼀个表达式为false，则不再计算第⼆个表达式，对于上⾯的表达式，当 loginUser为null时，后⾯的表达式不会执⾏，所以不会出现NullPointerException如果将&&改为&，则会 抛出NullPointerException异常。（ps：所以说当要⽤到逻辑与的时候&是毫⽆意义的） \n",
    " \n",
    " & 是⽤作位运算的。 \n",
    " \n",
    " 总结&是位运算，返回结果是int类型 &&是逻辑运算，返回结果是bool类型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 29. i++和++i有什么区别？\n",
    "\n",
    "1.i++是先赋值，然后再⾃增；++i是先⾃增，后赋值。 \n",
    "\n",
    "2.i=0，i++=0，++i=1； Console.WriteLine(i==i); 结果为true"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### as和is的区别\n",
    "\n",
    "as在转换的同时判断兼容性，如果⽆法进⾏转换，返回位null（没有产⽣新的对象），as转换是否成功判 断的依据是是否位null is只是做类型兼容性判断，并不执⾏真正的类型转换，返回true或false，对象为 null也会返回false。 \n",
    "\n",
    "as⽐is效率更⾼，as只需要做⼀次类型兼容检查"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "file_extension": ".cs",
   "mimetype": "text/x-csharp",
   "name": "C#",
   "pygments_lexer": "csharp",
   "version": "10.0"
  },
  "vscode": {
   "interpreter": {
    "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
